package scene.composants;

import java.awt.Color;
import java.awt.Composite;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.Iterator;

import UML.Attribut;
import UML.Classe;
import UML.Methode;

import scene.composants.elements.*;
import yaut.ENV;


/**
 * Composant Graphique representant une classe (UML Diagramme des classes)
 * 
 * @author Delmas Gabriel
 */
public class RepresentationClasse extends RepresentationComposant
{
	private static final long serialVersionUID = 816894361515087819L;
	
	/**
	 * Model de classe graphique
	 */
	private Classe classeModel;
	
	/**
	 * Ligne seperatrice du titre et des attributs
	 */
	private Ligne separateurT;
	
	/**
	 * Ligne seperatrice des attributs et des methodes
	 */
	private Ligne separateurAM;
	
	/**
	 * Police d'ecriture
	 */
	private FontMetrics fontMetrics;
	
	/**
	 * Affichage du contenu
	 */
	private boolean afficherContenu;
	
	/**
	 * Constructeur
	 * @param p la position (haut gauche)
	 */
	public RepresentationClasse(Point p)
	{
		super(p);
		largeur=120;
		hauteur=150;
		
		afficherContenu=true;
			
		Point pseperateur_hg=new Point(p.x,p.y+20);
		Point pseperateur_bd=new Point(p.x+largeur,p.y+20);
		
		separateurT=new Ligne(pseperateur_hg, pseperateur_bd);
		
		pseperateur_hg=new Point(p.x,p.y+40);
		pseperateur_bd=new Point(p.x+largeur,p.y+40);
		separateurAM=new Ligne(pseperateur_hg, pseperateur_bd);
		
		CalculGraphique();

	}
	
	/**
	 * Permet de lier la classe graphique a son modele
	 * @param classeModel le model
	 */
	public void ajouterModel(Classe classeModel)
	{
		this.classeModel= classeModel;
		CalculGraphique();
	}
	
	public Classe getModel(){return this.classeModel;}
	
	public void setAfficherContenu(boolean affiche)
	{
		if(!affiche)
		{
			hauteur=MIN_HAUTEUR;
			largeur=MIN_LARGEUR;
		}
		this.afficherContenu=affiche;
		CalculGraphique();
	}
	
	public boolean getAfficherContenu(){return this.afficherContenu;}
	
	/**
	 * Calcul des dimensions et des positions des seperateurs
	 */
	public void CalculGraphique()
	{
		int hauteurNom,hauteurAttributs,hauteurMethodes;
		
		if(afficherContenu)
		{
			hauteurNom=espace_texte;
			if(this.classeModel!=null)
			{
				if(this.classeModel.getAttributs().size()!=0)
					hauteurAttributs=espace_texte*this.classeModel.getAttributs().size();
				else
					hauteurAttributs=espace_texte;
			}
			else
				hauteurAttributs=espace_texte;
			if(this.classeModel!=null)
			{
				if(this.classeModel.getMethodes().size()!=0)
					hauteurMethodes=espace_texte*this.classeModel.getMethodes().size();
				else
					hauteurMethodes=espace_texte;
			}
			else
				hauteurMethodes=espace_texte;
			
			
			
			int newhauteur=hauteurNom+hauteurAttributs+hauteurMethodes+espace_texte;
			
			if(newhauteur>hauteur)
			{
				hauteur=newhauteur;
				minHauteur=newhauteur;
			}
		}
		else
		{
			hauteurNom=espace_texte;
			hauteurAttributs=espace_texte;
			hauteurMethodes=espace_texte;
		}
		
		hauteurNom+=5;
		hauteurAttributs+=5;
		hauteurMethodes+=5;
		
		super.CalculGraphique();
		
		
		Point pseperateur_hg=new Point(p.x,p.y+hauteurNom);
		Point pseperateur_bd=new Point(p.x+largeur,p.y+hauteurNom);
		
		separateurT=new Ligne(pseperateur_hg, pseperateur_bd);
		
		pseperateur_hg=new Point(p.x,p.y+hauteurNom+hauteurAttributs);
		pseperateur_bd=new Point(p.x+largeur,p.y+hauteurNom+hauteurAttributs);
		separateurAM=new Ligne(pseperateur_hg, pseperateur_bd);
		
	}
	
	/**
	 * Affichage graphique du composant
	 * @param g2d contexte graphique
	 */
	public void dessiner(Graphics2D g2d)
	{		
		fontMetrics = g2d.getFontMetrics();
		
		Color originalCouleur=g2d.getColor();
		Composite originalComposite = g2d.getComposite();
		
		//Trace de l'ombre
		if(ombreComposant)
			dessinerOmbre(g2d);
		
		g2d.setComposite(originalComposite);
		g2d.setColor(originalCouleur);
		
		
		//Si le composant est en train d'etre deplacer on ajoute l'effet de transparence
		if(estTransfere)
			g2d.setComposite(makeComposite(0.5F));
		
		
		//Trace de l'arriere plan du composant
		g2d.setColor(couleurFond);
		g2d.fillRect(cadre.x,cadre.y,cadre.width,cadre.height);
		
		//Trace du contour du composant
		g2d.setColor(couleurBordure);
		g2d.drawRect(cadre.x,cadre.y,cadre.width,cadre.height);
		
		//Trace des separateurs
		separateurT.dessiner(g2d);
		separateurAM.dessiner(g2d);
		
		g2d.setColor(couleurTexte);
		
		//On ecrit le contenu de la classe, chaque ligne de texte et raccourci en fonction de la largeur du composant
		String sTemp;
		sTemp = racourcirString(classeModel.getNom(),largeur);
		g2d.drawString(sTemp, p.x+espace_texte, p.y+espace_texte);
			
		if(afficherContenu)
		{
			int i=1;
			for (Iterator<Attribut> it = this.classeModel.getAttributs().iterator(); it.hasNext();)
			{
				Attribut attribut = it.next();
	
				sTemp = racourcirString(attribut.toString(),largeur);
				
				g2d.drawString(sTemp, separateurT.getPosition().x+espace_texte, separateurT.getPosition().y+espace_texte*i);
				i++;
			}
			
			i=1;
			for (Iterator<Methode> it = this.classeModel.getMethodes().iterator(); it.hasNext();)
			{
				Methode methode = it.next();
				
				sTemp = racourcirString(methode.toString(),largeur);
				
				g2d.drawString(sTemp, separateurAM.getPosition().x+espace_texte, separateurAM.getPosition().y+espace_texte*i);
				i++;
			}
		}
		//On affiche un symbole pour que visuellement on puisse voir que l'affichage du contenu de la classe a ete desactive
		else
		{
			Point pointT=new Point(separateurT.getPDestination().x-20, separateurT.getPDestination().y+9);
			Triangle triangleA=new Triangle(pointT, true);
			triangleA.dessiner(g2d);
		}	
		
		//Trace des extremites
		if(estSelectionne)
		{
			pext_hg.dessiner(g2d);
			pext_hd.dessiner(g2d);
			pext_bg.dessiner(g2d);
			pext_bd.dessiner(g2d);
		}
		
		//Valeurs original
		g2d.setColor(originalCouleur);
		g2d.setComposite(originalComposite);
		
	}
	
	/**
	 * Affichage graphique de l'ombre du composant
	 * @param g2d contexte graphique
	 */
	public void dessinerOmbre(Graphics2D g2d)
	{
		Composite originalComposite = g2d.getComposite();
		//Initialisaton de la transparence
		g2d.setComposite(makeComposite(0.5F));
		//darkGray pour l'effet
		g2d.setColor(Color.darkGray);
		g2d.drawLine(cadre.x,cadre.y+cadre.height+1,cadre.x+cadre.width+2,cadre.y+cadre.height+1);
		g2d.drawLine(cadre.x+cadre.width+1,cadre.y+cadre.height,cadre.x+cadre.width+1,cadre.y);
		//gray pour accentuer l'effet
		g2d.setColor(Color.gray);
		g2d.drawLine(cadre.x,cadre.y+cadre.height+2,cadre.x+cadre.width+2,cadre.y+cadre.height+2);
		g2d.drawLine(cadre.x+cadre.width+2,cadre.y+cadre.height,cadre.x+cadre.width+2,cadre.y);
		
		g2d.setComposite(originalComposite);
	}
	
	/**
	 * Permet de racourcir un String suivant une largeur en pixel
	 */
	private String racourcirString(String s, int largeurPixel)
	{
		String sTemp;
		String sFinal="";
		for(int j=0; j<=s.length(); j++)
		{
			sTemp=s.substring(0, j);
			if(fontMetrics.stringWidth(sTemp)<largeur-espace_texte)
				sFinal=sTemp;
		}
		return sFinal;
	}
	
	/**
	 * Double clique sur la classe
	 * Permet d'editer la classe
	 */
	public void actionDoubleClique()
	{
		ENV.FRAME.getControleur().modifierClasse(this);
	}
	
	/**
	 * Affiche le menu contextuel du clique droit
	 * Permet de visualiser les actions possibles sur la classe
	 */
	public void actionMenuContextuel(Point p)
	{
		ENV.FRAME.getControleur().afficherMenuContextuel(this, p);
	}
	
}
